/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sasp_udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import sasp_messages.SASPCommand;

/**
 *
 * @author mauriello
 */
public class UDPTransceiver implements Runnable {
    private int portNum;
    private ArrayList<UDPListener> udpListeners;
    private Thread udpThread;

    public final static int DEFAULT_PORT    = 12345;
    public final static int MAX_PACKET_SIZE = 65507;

    public UDPTransceiver( ) {
        this( DEFAULT_PORT );
    }

    public UDPTransceiver( int _portNum ) {
        udpThread = new Thread(this);
        udpListeners = new ArrayList<UDPListener>();
        portNum = _portNum;
        udpListeners.clear();
        startUdpThread( );
    }

    public boolean addUdpListener( UDPListener _l ) {
        return udpListeners.add(_l);
    }

    public boolean removeUdpListener( UDPListener _l ) {
        return udpListeners.remove(_l);
    }

    public boolean transmitUdpMessage( String _hostname, int _port, String _txData ) {
        boolean retVal = true;

        try {
            InetAddress    server = InetAddress.getByName(_hostname);
            DatagramSocket socket = new DatagramSocket();
            DatagramPacket packet = new DatagramPacket(_txData.getBytes(), _txData.getBytes().length, server, _port);
            socket.send(packet);
        } catch (Exception ex) {
            retVal = false;
            Logger.getLogger(UDPTransceiver.class.getName()).log(Level.SEVERE, null, ex);
        }

        return retVal;
    }

    private void startUdpThread( ) {
        if( !udpThread.isAlive() ) {
            System.out.println("UDP - Starting Thread @ Port: " + portNum );
            udpThread.start();
        }
    }

    private synchronized void handleRcvData( UDPMessage _inData ) {
        Iterator<UDPListener> udpIter = udpListeners.iterator();
        while ( udpIter.hasNext() ){
            udpIter.next().handleMessage(_inData);
        }
    }

    public void run() {
        byte [] buffer = new byte[UDPTransceiver.MAX_PACKET_SIZE];
        try {
            DatagramSocket server = new DatagramSocket(portNum);
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

            while (true) {  // DO FOREVER
                System.out.println("UDP - Waiting for Packet");
                // Wait for packet from client
                server.receive(packet);
      
                UDPMessage theMessage = new UDPMessage(packet.getAddress().getHostAddress(), new String(packet.getData()));
                
                System.out.println("UDP - Rcv: " + theMessage.getTheMessage().trim());

                // Notify Listeners
                this.handleRcvData(theMessage);

                // Reset Packet Length for Next Packet
                packet.setLength(buffer.length);
                theMessage = null;
            }
        } catch (Exception ex) {
            Logger.getLogger(UDPTransceiver.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

